package model

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"sync"

	_ "github.com/go-sql-driver/mysql"
)

type mysqlOptions struct {
	Host     string
	Username string
	Password string
	Database string
	Port     int
}

var rwmu sync.RWMutex
var mu sync.Mutex
var mysqls map[string]*sql.DB

func parseMysqlJson(str string) (mysqlOptions, error) {
	var config mysqlOptions
	err := json.Unmarshal([]byte(str), &config)

	return config, err
}
func createMysql(str string) {
	if _, ok := mysqls[str]; ok {
		log.Println("mysql连接已存在")
		return
	}
	config, err := parseMysqlJson(str)
	if err != nil {
		log.Println("SrcConnectionStr parse error ")
		return
	}
	dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s",
		config.Username, config.Password, config.Host, config.Port, config.Database)
	db, err := sql.Open("mysql", dbDSN)
	if err != nil {
		log.Println(err)
	}
	err = db.Ping()
	if err != nil {
		log.Println("ping err", err)
		// return
	}
	log.Println("mysql connect success, dbDSN")
	mysqls[str] = db
}

func GetMysqlConn(str string) *sql.DB {
	rwmu.RLock()
	if mysqls != nil {
		client, ok := mysqls[str]
		if ok {
			rwmu.RUnlock()
			return client
		}
	}
	rwmu.RUnlock()
	mu.Lock()
	if mysqls == nil { // NOTE: must recheck for nil
		mysqls = make(map[string]*sql.DB)
	}
	createMysql(str)
	client := mysqls[str]
	mu.Unlock()
	return client
}

// 查询数据,取所有字段,不采用结构体
func RawQueryAllField(client *sql.DB, sql string) (map[int]map[string]string, error) {
	result := make(map[int]map[string]string)
	//查询数据，取所有字段
	row, err := client.Query(sql)
	if err != nil {
		log.Println(err)
		return result, err
	}
	defer row.Close()

	//返回所有列
	cols, _ := row.Columns()

	//这里表示一行所有列的值，用[]byte表示
	vals := make([][]byte, len(cols))

	//这里表示一行填充数据
	scans := make([]interface{}, len(cols))
	//这里scans引用vals，把数据填充到[]byte里
	for k := range vals {
		scans[k] = &vals[k]
	}

	i := 0
	for row.Next() {
		//填充数据
		row.Scan(scans...)
		//每行数据
		row := make(map[string]string)
		//把vals中的数据复制到row中
		for k, v := range vals {
			key := cols[k]
			//这里把[]byte数据转成string
			row[key] = string(v)
		}
		//放入结果集
		result[i] = row
		i++
	}
	return result, nil
}
